import { Injectable, InternalServerErrorException } from '@nestjs/common';
import * as qiniu from 'qiniu';
import * as Multer from 'multer';
import * as stream from 'stream';
import { UserUploadEntity } from '@/entity/user-upload.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ConfigService } from '@nestjs/config';
import { v4 as uuidv4 } from 'uuid';
import * as path from 'path';
@Injectable()
export class UploadService {
  constructor(
    @InjectRepository(UserUploadEntity)
    private readonly userUploadRepository: Repository<UserUploadEntity>,
    private readonly configService: ConfigService,
  ) {}
  /**
   * 上传到七牛云
   * @param file 上传的文件
   */
  async uploadToQiniu<T extends 'image' | 'video'>(
    file: Multer.File,
    type: T,
  ): Promise<string> {
    const accessKey = this.configService.get('QINIU_ACC'); // 七牛云accessKey
    const secretKey = this.configService.get('QINIU_SEC'); // 七牛云密钥
    const bucket = this.configService.get('QINIU_BUCKET'); // 七牛云存储空间名
    const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
    const options = {
      scope: bucket, // 上传文件的存储空间
    };
    const putPolicy = new qiniu.rs.PutPolicy(options); // 上传策略
    const uploadToken = putPolicy.uploadToken(mac); // 上传凭证
    const formUploader = new qiniu.form_up.FormUploader({
      zone: qiniu.zone[this.configService.get('QINIU_ZONE')],
    }); // 上传配置
    const putExtra = new qiniu.form_up.PutExtra(); // 上传文件
    const fileStream = stream.Readable.from(file.buffer); // 上传文件流,可读流
    const cleanedFileName = file.originalname.replace(/[^\x00-\xff]/g, '');
    const uniqueFileName = `${uuidv4()}${path.extname(cleanedFileName)}`;
    const key = `${type}/${uniqueFileName}`; // 上传的文件名key值
    return new Promise<string>((resolve, reject) => {
      formUploader.putStream(
        uploadToken,
        key,
        fileStream,
        putExtra,
        (respErr, respBody, respInfo) => {
          if (respErr) {
            console.error(respErr);
            throw new InternalServerErrorException(respErr.message); // 上传失败
          }
          if (respInfo.statusCode == 200) {
            resolve(`http://${process.env.QINIU_DOMAIN}/${respBody.key}`); // 上传成功-返回图片地址
          } else {
            console.error(respInfo.statusCode, respBody);
            throw new InternalServerErrorException(respInfo);
          }
        },
      );
    });
  }

  /**
   * 将上传的图片保存到数据库
   * @param userId 用户id
   * @param ip 用户ip
   * @param fileUrl 图片地址
   */
  async uploadImage(
    userId: number,
    userIp: string,
    uploadUrl: string,
  ): Promise<UserUploadEntity> {
    const upload = new UserUploadEntity();
    upload.userId = userId;
    upload.userIp = userIp;
    upload.uploadUrl = uploadUrl;
    upload.type = 'image';
    return this.userUploadRepository.save(upload);
  }

  /**
   * 将上传的视频保存到数据库
   * @param userId 用户id
   * @param ip 用户ip
   * @param fileUrl 视频地址
   */
  async uploadVideo(
    userId: number,
    userIp: string,
    uploadUrl: string,
  ): Promise<UserUploadEntity> {
    const upload = new UserUploadEntity();
    upload.userId = userId;
    upload.userIp = userIp;
    upload.uploadUrl = uploadUrl;
    upload.type = 'video';
    return this.userUploadRepository.save(upload);
  }
}
